package ufrgs.ia.tetralath.brain;

import ufrgs.ia.tetralath.Tetralath.PLAYER;
import ufrgs.ia.tetralath.models.GameMomentum;

/**
 * <b>Minimax implementation</b> <br>
 * This will contain several static functions to calculate the minimax. <br>
 * By now I think that this class will mainly have a method that receives <br>
 * a certain configuration of the game board and will return as a result <br>
 * the coordinates of the next piece that the player should click. 
 * @author Fernando
 *
 */
public class Minimax {

	private static final int LESS_INFINITY = -10000;
	private static final int INFINITY = 10000;
	
	/** maximum depth that the minimax can reach */
	public static int MAX_MINIMAX_DEPTH = 3;
	
	public GameMomentum getBestMove(GameMomentum _currentState) {
		
		int currentDepth = 0;
		//int maxValue = maxValue((GameMomentum)_currentState.clone(), LESS_INFINITY, INFINITY, 0);
		int maxValue = maxValue(_currentState, LESS_INFINITY, INFINITY, currentDepth);
		
		GameMomentum bestOption = null;
		
		for(GameMomentum aux : _currentState.getSucessors()) {
			if(bestOption == null)
				bestOption = aux;
			
			if(aux.getValue() == maxValue)
				return aux;
			else if(aux.getValue() > bestOption.getValue()) {
				bestOption = aux;
			}
		}
		
		return bestOption;
	}
	
	/**
	 * 
	 * @param _currentState
	 * @param _player
	 * @return
	 */
	private int maxValue(GameMomentum _currentState, int alfa, int beta, int currentDepth) {
		
		if((currentDepth >= MAX_MINIMAX_DEPTH) || (_currentState.isLeaf())) {
			return _currentState.getValue();
		} else {
			int value = LESS_INFINITY;
			
			_currentState.generateSucessors(PLAYER.MINIMAX);
			
			for(GameMomentum sucessor : _currentState.getSucessors()) {
				
				value = Math.max(value, minValue(sucessor, alfa, beta, currentDepth + 1));
				
				if(value >= beta)
					return value;
				
				alfa = Math.max(alfa, value);
				
			}
			return value;
		}
	}
	
	/**
	 * 
	 * @param _currentState
	 * @param _player
	 * @return
	 */
	private int minValue(GameMomentum _currentState, int alfa, int beta, int currentDepth) {
		
		if((currentDepth >= MAX_MINIMAX_DEPTH) || (_currentState.isLeaf())) {
			return _currentState.getValue();
		} else {
		
			int value = INFINITY;
			
			_currentState.generateSucessors(PLAYER.HUMAN);
						
			for(GameMomentum sucessor : _currentState.getSucessors()) {
				
				value = Math.min(value, maxValue(sucessor, alfa, beta, currentDepth + 1));
				
				if(value <= alfa)
					return value;
				
				beta = Math.min(beta, value);
			}
			
			return value;
		}
	}
}
